﻿using System;

using BizElements.Core;

namespace BizElements.BusinessLayer
{
    /// <summary>Reflection based implementation of generic interface for managing complex properties, ie. child/extension entities linked to parent entity via 1-to-1 relations. 
    /// Primary key of such child is also a foreign key to parent entity. Assumes method naming conventions as implememented in BizElements XML templates that generate business object classes.</summary>
    public sealed class ReflectionComplexPropertyAdapter : IComplexPropertyAdapter
    {
        /// <summary>Initializes a new instance of <b>ReflectionComplexPropertyAdapter</b> class.</summary>
        /// <param name="propertyName">Complex property name.</param>
        public ReflectionComplexPropertyAdapter(string propertyName)
        {
            this.PropertyName = propertyName;
        }

        /// <summary>Complex property name.</summary>
        public string PropertyName { get; private set; }

        /// <summary>Gets property value, ie. child entity.</summary>
        /// <param name="parentEntity">Parent object that owns the child entity property worked by current adapter.</param>
        /// <returns>Child entity or <b>null</b> if it doesn't exist or hasn't been fetched.</returns>
        public IDataObject GetChild(IBusinessObject parentEntity)
        {
            return ReflectionUtil.GetPublicPropertyValue(parentEntity, this.PropertyName) as IDataObject;
        }

        /// <summary>Fetches child entity if it exists.</summary>
        /// <param name="parentEntity">Parent object that owns the child entity property worked by current adapter.</param>
        public void FetchChild(IBusinessObject parentEntity)
        {
            string methodName = string.Format("Fetch{0}", this.PropertyName);
            ReflectionUtil.InvokeMethod(parentEntity, methodName, new object[0]);
        }

        /// <summary>Creates a new adapter that is a copy of the current instance.</summary>
        /// <returns>A new object that is a copy of the current instance.</returns>
        public IComplexPropertyAdapter Clone()
        {
            return new ReflectionComplexPropertyAdapter(this.PropertyName);
        }
    }
}
